﻿using System;
using System.Text;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Input;
using Editeur_map;


namespace lapinou_game2
{
    class Rab
    {
        Sprite lapin_right, lapin_left;
        Vector2 position;
        Vector2 jauge;
        Vector2 cursorpos;
        Vector2 lastPosition;
        ContentManager content;
        GraphicsDeviceManager graphics;
        Sound sound;
        Map_State CurrentMap;

        HitControl hc;
        BoundingSphere rabArea;

        //Gestion des missiles
        List<Projectile> projectiles;
        int number_proj = 0;
        int compteur_usi = 0;
        
        int sol = 30;
        int jaugexmax = 6;
        int jaugeymax = 17;
        int vitesse = 5;
        int sens = 1;
        int g = 10;
        int winWidth;
        int winHeight;

        float mass_lapin = (float)0.8f;
        float decroissance_jaugey = (float)0.4f;
        float decroissance_jaugex = (float)0.08f;
        float temps = 1;

        // left : le lapin regarde vers la gauche, right : la droite
        string rab_direction = "right";
        string last_rab_direction = "";

        public Rab(ContentManager Content, int winWidth, int winHeight, GraphicsDeviceManager Graphics, Vector2 Cursorpos, Map_State currentMap)
        {
            // taille de la fenêtre de jeu
            this.winWidth = winWidth;
            this.winHeight = winHeight;

            CurrentMap = currentMap;
            // creation d'une instance de bounding box
            hc = new HitControl(CurrentMap, 0, 0);

            content = Content;
            graphics = Graphics;
            cursorpos = Cursorpos;
            number_proj = 0;

            // position du lapin au tout début
            position.X = 0;
            position.Y = 0;
            jauge.X = 0;
            jauge.Y = 0;

            lapin_right = new Sprite(Vector2.Zero);
            lapin_left = new Sprite(Vector2.Zero);

            projectiles = new List<Projectile>();
            sound = new Sound();

            this.content = Content;
        }

        // fonction par défaut
        public void loadRab()
        {
            lapin_right.LoadContent(content, "image/rab_right"); // lapin
            lapin_left.LoadContent(content, "image/rab_left");
            
        }

        // permet de charger un autre style de lapin
        public void loadRab(string rabpath)
        {
            lapin_right.LoadContent(content, rabpath); // lapin
            lapin_left.LoadContent(content, rabpath);
        }

        public void moveRab(KeyboardState keyboardstate, KeyboardState last_keyboardstate, int speed, Cursor cursor)
        {

            this.vitesse = speed;
            temps += 0.8f;

            lastPosition = position;

            List<Projectile> temp_remove_proj = new List<Projectile>();
            
            // -------------------- \\
            // ----  Projectiles ---\\
            // ---------------------\\
            cursorpos = cursor.getPos();
            if (position.X - lapin_right.largeur() > cursorpos.X)
            { rab_direction = "left"; }
            else if (position.X + lapin_right.largeur() < cursorpos.X)
            { rab_direction = "right"; }
            else if (cursorpos.Y < position.Y)
            { rab_direction = "haut"; }
            else
            { rab_direction = "bas"; }

            if (compteur_usi >= 10)
            {
                keyboardstate.IsKeyUp(Keys.A);
                if (compteur_usi < 20)
                {
                    compteur_usi++;
                }
                else
                {
                    compteur_usi = 0;
                }
            }
            else if (keyboardstate.IsKeyDown(Keys.A))
            {
                Projectile proj = new Projectile(content, graphics, new Vector2(position.X, position.Y + 18), rab_direction, cursorpos, lapin_right.hauteur(), lapin_right.largeur());
                compteur_usi++;
                proj.LoadContent(content);
                proj.Initialize(cursor, getpos());
                projectiles.Add(proj);
                number_proj++;
                sound.PlaySound(content, "blaster", 0.1f);
                
            }
            foreach (Projectile proj in projectiles)
            {
                if (proj.screen()== false)
                {
                    temp_remove_proj.Add(proj);
                    number_proj--;
                }
                else
                {
                    proj.UpDate(cursor);
                }
            }

            foreach (Projectile proj in temp_remove_proj)
                projectiles.Remove(proj);

            temp_remove_proj.Clear();

            // gère l'arrivée au sol
            if (hc.getHitTestValue(new BoundingSphere(
                    new Vector3(this.position.X, this.position.Y + 5, 0), (float)lapin_right.hauteur())) == HitControl.Collision.Yes)
            {
                jauge.X = 0;
                jauge.Y = 0;
                sens = 1;
            }

            // gère la gravité + cinétique horizontale
            if (hc.getHitTestValue(new BoundingSphere(
                    new Vector3(this.position.X, this.position.Y + 1, 0), (float)lapin_right.hauteur())) != HitControl.Collision.Yes)
            {
                position.Y += mass_lapin * g - jauge.Y;
                position.X = position.X + jauge.X;
            }

            // gère la décroissance de la jauge cinétique horizontale
            if (jauge.X < 0)
            {
                jauge.X += decroissance_jaugex;
            }
            else if (jauge.X > 0)
            {
                jauge.X -= decroissance_jaugex;
            }

            // gère la décroissance de la jauge cinétique verticale
            if (jauge.Y == 400)
            {
                sens = -1;
            }
            else if (jauge.Y > 0)
                jauge.Y -= decroissance_jaugey;


            // collisions avec le bord
            if (position.X > winWidth - 30)
                position.X = winWidth - 30;

            if (position.X < 0)
                position.X = 0;

            if (position.Y > winHeight - sol)
                position.Y = winHeight - sol;

            if (position.Y < 0)
                position.Y = 0;

            // déplacement clavier

            // flèche droite
            if (keyboardstate.IsKeyDown(Keys.Right))
            {

                if (jauge.Y == 0)
                {
                    position.X += vitesse;
                    if (jauge.X >= -100 || jauge.X <= 100)
                        jauge.X = jaugexmax;
                }
                else
                    position.X += 1f;
            }

            // flèche gauche
            if (keyboardstate.IsKeyDown(Keys.Left))
            {

                if (jauge.Y == 0)
                {
                    position.X -= vitesse;
                    if (jauge.X >= -100 || jauge.X <= 100)
                        jauge.X = -jaugexmax;
                }
                else
                    position.X -= 1f;
                
            }

            // flèche bas
            if (keyboardstate.IsKeyDown(Keys.Down)
                
                                                                                                                                      )
            {
                if (hc.getHitTestValue(getRabSphere()) != HitControl.Collision.Yes)
                    position.Y += 2;
            }

            // flèche haut
            if (keyboardstate.IsKeyDown(Keys.Up))
                
            {    
                    if (jauge.Y == 0 && sens == 1)
                    {

                        jauge.Y = jaugeymax;
                        position.Y -= jauge.Y;
                    }                
            }

            // on englobe le lapin d'une sphère de contact
            rabArea = new BoundingSphere(new Vector3(this.position, 0), (float)lapin_right.hauteur());

            // s'il y a collision alors on place le lapin à sa position precedente
            if (hc.getHitTestValue(getRabSphere()) != HitControl.Collision.Yes)
            {
                // on met à jour les coordonnées du lapin         
                lapin_right.Position = new Vector2(position.X, position.Y);
                lapin_left.Position = new Vector2(position.X, position.Y);
            }                
            else
            {
                lapin_right.Position = new Vector2(position.X, lastPosition.Y );
                lapin_left.Position = new Vector2(position.X, lastPosition.Y);
            }
        }

        public void drawRab(SpriteBatch spriteBatch)
        {
            foreach (Projectile proj in projectiles)
                proj.Draw(spriteBatch);

            if (rab_direction == "right")
                lapin_right.Draw(spriteBatch);
            else if (rab_direction == "left")
                lapin_left.Draw(spriteBatch);
            else if (last_rab_direction == "right")
                lapin_right.Draw(spriteBatch);
            else
                lapin_left.Draw(spriteBatch);

            if (rab_direction != "haut")
                last_rab_direction = rab_direction;
        }

        public void setWinSizes(int winWidth, int winHeight)
        {
            this.winWidth = winWidth;
            this.winHeight = winHeight;
        }

        public Vector2 getpos()
        {
            return position;
        }        

        public BoundingSphere getRabSphere()
        {
            return this.rabArea;
        }

        public void setRabPosition (int posX, int posY)
        {
            this.position.X = posX;
            this.position.Y = posY;
        }

        public void setRabPosition (Vector2 position)
        {
            this.position = position;
        }

        public void reLoadBounding(int xdecal, int ydecal)
        {
            hc.clearBoundingList();
            hc = new HitControl(CurrentMap, xdecal, ydecal);
        }
    }
}